(function( $ ){
  $.fn.ellipsis = function( options ) {
    return this.each(function(){
      var $this = $( this ),
          data = $this.data( 'ellipsis' ),
          options = $.extend({
            length: 300,
            selector: '*'
          }, options);
      
      if ( typeof data !== 'undefined' ) {
        return; 
      }

      var $children = $this.find( options.selector ),
          $el,
          text,
          textLen,
          charCount = 0,
          cutoffIndex,
          $span,
          $hidden,
          $ellipse;

      $this.addClass( 'ui-ellipsis' );

      for ( var i = 0, len = $children.length; i < len; i++ ) {
        $el = $children.eq( i );
        text = $el.html();
        textLen = text.length;
        charCount += textLen;

        if ( charCount >= options.length ) {
          cutoffIndex = text.indexOf( ' ', textLen - ( charCount - options.length ) );
          $el.html( text.substring( 0, cutoffIndex ) );
          $ellipse = $( '<span>&hellip;&nbsp;</span>' )
            .addClass( 'ui-ellipsis-text' )
            .appendTo( $el );
          $( '<a href="#">Show More</a>' )
            .addClass( 'ui-ellipsis-toggle')
            .on( 'click', function( event ) {
              event.preventDefault();
              data.hidden && data.hidden.show();
              $( this ).hide();
              $ellipse.hide();
            })
            .appendTo( $el );
          $span = $( '<span>' + text.substring( cutoffIndex ) + '</span>' )
            .addClass( 'ui-ellipsis-hidden' )
            .appendTo( $el );

          $hidden = $span.add( $children.slice( i + 1 ) ).hide();
          break;
        }
      }

      data = {
        hidden: $hidden
      };
      $this.data( 'ellipsis', data );

    });
  };
})( $ );